// WebSocket 连接管理器
package websocket

import (
	"gohub/app/services"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

// 定义全局变量
var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		// 允许所有origin
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

// Client 表示一个WebSocket客户端连接
type Client struct {
	ID       string          // 客户端唯一ID
	Conn     *websocket.Conn // WebSocket连接
	Send     chan []byte     // 发送消息的通道
	UserID   string          // 关联的用户ID
	Status   string          // 连接状态
	LastPing time.Time       // 最后心跳时间
}

// WebSocketManager 管理所有WebSocket连接
type WebSocketManager struct {
	clients      map[string]*Client // 所有客户端
	broadcast    chan []byte        // 广播消息通道
	register     chan *Client       // 注册通道
	unregister   chan *Client       // 注销通道
	mu           sync.RWMutex       // 读写锁
	PingInterval time.Duration      // 心跳间隔
	PingTimeout  time.Duration      // 心跳超时
}

// NewWebSocketManager 创建新的WebSocket管理器
func NewWebSocketManager() *WebSocketManager {
	return &WebSocketManager{
		clients:      make(map[string]*Client),
		broadcast:    make(chan []byte),
		register:     make(chan *Client),
		unregister:   make(chan *Client),
		PingInterval: 30 * time.Second,
		PingTimeout:  60 * time.Second,
	}
}

// Start 启动WebSocket管理器
func (m *WebSocketManager) Start() {
	for {
		select {
		case client := <-m.register:
			m.registerClient(client)
		case client := <-m.unregister:
			m.unregisterClient(client)
		case message := <-m.broadcast:
			m.broadcastMessage(message)
		}
	}
}

// registerClient 注册新客户端
func (m *WebSocketManager) registerClient(client *Client) {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.clients[client.ID] = client
	client.Status = "connected"
	log.Printf("Client %s connected (Total: %d)", client.ID, len(m.clients))
}

// unregisterClient 注销客户端
func (m *WebSocketManager) unregisterClient(client *Client) {
	m.mu.Lock()
	defer m.mu.Unlock()

	if _, ok := m.clients[client.ID]; ok {
		close(client.Send)
		delete(m.clients, client.ID)
		client.Status = "disconnected"
		log.Printf("Client %s disconnected (Total: %d)", client.ID, len(m.clients))
	}
}

// HandleConnection 处理WebSocket连接
func (m *WebSocketManager) HandleConnection(c *gin.Context) {
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Printf("WebSocket upgrade error: %v", err)
		return
	}

	// 从查询参数获取客户端ID和用户ID
	clientID := c.Query("cid")
	if clientID == "" {
		clientID = generateClientID()
	}
	userID := c.Query("uid")
	log.Printf("处理WebSocket连接 clientID: %s, userID: ", clientID)

	client := &Client{
		ID:     clientID,
		Conn:   conn,
		Send:   make(chan []byte, 256),
		UserID: userID,
		Status: "connecting",
	}

	m.register <- client

	// 启动读写协程
	go m.readPump(client)
	go m.writePump(client)
}

// readPump 处理读消息
func (m *WebSocketManager) readPump(client *Client) {
	defer func() {
		m.unregister <- client
		client.Conn.Close()
	}()

	// 设置初始读超时（使用管理器配置）
	client.Conn.SetReadDeadline(time.Now().Add(m.PingTimeout))

	// 设置心跳检测（收到Pong后重置超时）
	client.Conn.SetPongHandler(func(string) error {
		client.LastPing = time.Now()
		client.Conn.SetReadDeadline(time.Now().Add(m.PingTimeout))
		return nil
	})

	for {
		messageType, message, err := client.Conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Printf("Read error: %v", err)
			}
			break
		}

		switch messageType {
		case websocket.PingMessage:
			// 响应Ping（标准协议应该由客户端发Ping，服务端回Pong）
			err := client.Conn.WriteMessage(websocket.PongMessage, nil)
			if err != nil {
				log.Printf("Failed to send protocol pong: %v", err)
				return
			}
			log.Printf("回复ping消息\n", string(message))
		case websocket.TextMessage:
			// 兼容文本ping消息
			if string(message) == "ping" {
				if err := client.Conn.WriteMessage(websocket.TextMessage, []byte("pong")); err != nil {
					log.Printf("Failed to send text pong: %v", err)
				}
				continue
			}

			// 处理其他业务消息...
			//log.Printf("获取客户端发送的消息 client: %s, message: %s\n", client.ID, string(message))
			sendMessage, err := services.HandleReceiveMessage(message)
			if err != nil {
				log.Printf("处理异常: %s\n", err)
			}

			if len(sendMessage) > 0 {
				if err := client.Conn.WriteMessage(websocket.TextMessage, []byte(sendMessage)); err != nil {
					log.Printf("Failed to send text: %v", err)
				}
			}
		}
	}
}

// writePump 处理写消息
func (m *WebSocketManager) writePump(client *Client) {
	// 使用管理器配置的心跳间隔
	pingTicker := time.NewTicker(m.PingInterval)
	defer func() {
		pingTicker.Stop()
		client.Conn.Close()
	}()

	for {
		select {
		case message, ok := <-client.Send:
			// 设置写超时（心跳超时的一半时间）
			client.Conn.SetWriteDeadline(time.Now().Add(m.PingTimeout / 2))

			if !ok {
				// 通道关闭，发送关闭帧
				client.Conn.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}

			w, err := client.Conn.NextWriter(websocket.TextMessage)
			if err != nil {
				return
			}
			log.Printf("发送的消息: %s\n", string(message))
			w.Write(message)

			// 发送队列中的其他消息
			n := len(client.Send)
			for i := 0; i < n; i++ {
				w.Write(<-client.Send)
			}

			if err := w.Close(); err != nil {
				return
			}
		case <-pingTicker.C:
			// 发送Ping消息
			client.Conn.SetWriteDeadline(time.Now().Add(m.PingTimeout / 2))
			if err := client.Conn.WriteMessage(websocket.PingMessage, nil); err != nil {
				log.Printf("Failed to send ping to %s: %v", client.ID, err)
				return
			}
			// log.Printf("Sent ping to %s", client.ID) // 调试日志
		}
	}
}

// broadcastMessage 广播消息给所有客户端
func (m *WebSocketManager) broadcastMessage(message []byte) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	for _, client := range m.clients {
		select {
		case client.Send <- message:
		default:
			close(client.Send)
			delete(m.clients, client.ID)
		}
	}
}

// SendToClient 发送消息到指定客户端
func (m *WebSocketManager) SendToClient(clientID string, message []byte) bool {
	m.mu.RLock()
	defer m.mu.RUnlock()

	client, ok := m.clients[clientID]
	if !ok {
		return false
	}

	select {
	case client.Send <- message:
		return true
	default:
		return false
	}
}

// SendToUser 发送消息到指定用户的所有客户端
func (m *WebSocketManager) SendToUser(userID string, message []byte) int {
	m.mu.RLock()
	defer m.mu.RUnlock()

	count := 0
	for _, client := range m.clients {
		if client.UserID == userID {
			select {
			case client.Send <- message:
				count++
			default:
			}
		}
	}
	return count
}

// GetClientstatus 获取客户端状态
func (m *WebSocketManager) GetClientstatus(clientID string) (string, bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	client, ok := m.clients[clientID]
	if !ok {
		return "", false
	}
	return client.Status, true
}

// GetAllClients 获取所有客户端信息
func (m *WebSocketManager) GetAllClients() map[string]string {
	m.mu.RLock()
	defer m.mu.RUnlock()

	result := make(map[string]string)
	for id, client := range m.clients {
		result[id] = client.Status
	}
	return result
}

// generateClientID 生成客户端ID
func generateClientID() string {
	return "client-" + time.Now().Format("20060102-150405.000")
}

// 解决控制器中调用
func (m *WebSocketManager) SendBroadcast(message []byte) {
	m.broadcast <- message
}
